﻿using System.Collections.Generic;
using EmbeddedSharp.Core;
using EmbeddedSharp.Scripting.Function;

namespace EmbeddedSharp.Scripting
{
    public class UserDefinedFunctionParser
    {
        private readonly IExpressionParserFactory pf;

        private readonly IUserDefinedFunctionFactory udfFactory;

        public UserDefinedFunctionParser(IExpressionParserFactory pf)
            : this(pf, new DefaultUserDefinedFunctionFactory())
        {
        }

        public UserDefinedFunctionParser(
            IExpressionParserFactory pf, IUserDefinedFunctionFactory udfFactory)
        {
            this.pf = pf;
            this.udfFactory = udfFactory;
        }

        public UserDefinedFunctionNode Parse(string input)
        {
            string name = string.Empty;
            string funcBody = string.Empty;

            var parameters = new List<string>();
            var lexer = new Lexer(input);
            name = lexer.NextToken(TokenType.IDENTIFIER).Value;
            string comment = lexer.LastComment;
            Token token = lexer.NextToken(TokenType.LeftBrace);
            while (lexer.HasMoreTokens())
            {
                token = lexer.NextToken(
                    TokenType.IDENTIFIER, TokenType.Comma,
                    TokenType.RightBrace, TokenType.RightSquareBrace);
                if (token.TokenType == TokenType.RightBrace || token.TokenType == TokenType.RightSquareBrace)
                {
                    break;
                }
                else if (token.TokenType == TokenType.Comma)
                {
                    continue;
                }

                parameters.Add(token.Value);
            }
            lexer.NextToken(TokenType.Declare);
            while (lexer.HasMoreTokens())
            {
                token = lexer.NextToken();
                funcBody = funcBody + token.Value;
            }
            parameters.Reverse();
            UserDefinedFunctionNode udf
                = udfFactory.Create();
            udf.Name = name;
            udf.Comment = lexer.LastComment;
            udf.Arguments = parameters.ToArray();
            udf.FuncBody = funcBody;
            //udf.Context = this.Context;
            udf.ParserFactory = pf;

            return udf;
        }
    }
}